package me.sdevil507.org.controller;

import lombok.extern.slf4j.Slf4j;
import me.sdevil507.biz.common.exceptions.PhoneNumberExistedException;
import me.sdevil507.biz.common.sms.captcha.enums.CaptchaType;
import me.sdevil507.biz.common.sms.captcha.service.CaptchaService;
import me.sdevil507.org.dto.*;
import me.sdevil507.org.mapper.OrgUserMapper;
import me.sdevil507.org.mapper.OrgUserRelMapper;
import me.sdevil507.org.po.OrgUserPo;
import me.sdevil507.org.po.OrgUserRelPo;
import me.sdevil507.org.service.OrgService;
import me.sdevil507.org.service.OrgUserService;
import me.sdevil507.supports.helper.Md5PasswordHelper;
import me.sdevil507.supports.result.ApiResultDTO;
import me.sdevil507.supports.result.ApiResultGenerator;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.shiro.realm.OrgUsernamePasswordRealm;
import me.sdevil507.supports.status.ApiStatusCode;
import me.sdevil507.supports.util.AESUtil;
import me.sdevil507.systemAssist.Constant.SystemAssistConstant;
import me.sdevil507.systemAssist.systemLog.annotation.OperLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 专家用户Controller
 *
 * @author sdevil507
 * created on 2020/8/4
 */
@RestController
@RequestMapping("/api/expert/user")
@Slf4j
public class ExpertUserController {

    @Autowired
    private OrgUserService orgUserService;

    @Autowired
    private OrgUserMapper orgUserMapper;

    @Autowired
    private Md5PasswordHelper md5PasswordHelper;

    @Autowired
    private OrgService orgService;

    @Autowired
    private OrgUserRelMapper orgUserRelMapper;

    @Autowired
    private OrgUsernamePasswordRealm orgUsernamePasswordRealm;

    @Autowired
    private CaptchaService captchaService;

    /**
     * 获取用户个人信息
     *
     * @return 个人信息
     */
    @GetMapping("/info")
    @RequiresPermissions("expert:info:view")
    public ApiResultDTO info() {
        String phoneNumber = OrgAccountHelper.getUsername();
        OrgUserPo orgUserPo = orgUserService.readOneByPhoneNumber(phoneNumber);
        OrgUserResultDto orgUserResultDto = orgUserMapper.po2dto(orgUserPo);
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), orgUserResultDto);
    }

    /**
     * 机构修改用户信息
     *
     * @param dto 参数
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.EXPERT, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_UPDATE, operDesc = "机构修改用户信息")
    @PostMapping("/update")
    @RequiresPermissions("expert:info:edit")
    public ApiResultDTO update(@RequestBody OrgUserParamsDto dto) {
        try {
            orgUserService.update(dto);
        } catch (PhoneNumberExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_EXISTED.getCode(), ApiStatusCode.ACCOUNT_EXISTED.getDescription());
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }


    /**
     * 更改密码
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.EXPERT, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.MODIFY_PWD, operDesc = "")
    @PostMapping("/changePassword")
    @RequiresPermissions("expert:info:change:pwd")
    public ApiResultDTO changePassword(@RequestBody @Valid OrgUserChangePasswordParamsDto dto) {
        String phoneNumber = OrgAccountHelper.getUsername();
        OrgUserPo orgUserPo = orgUserService.readOneByPhoneNumber(phoneNumber);
        if(null!=orgUserPo && !StringUtils.isEmpty(orgUserPo.getPassword())){
            // 校验原始密码
            if (!Objects.equals(AESUtil.encryptPassword(dto.getOldPassword()), orgUserPo.getPassword())) {
                return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_OLD_PWD_INVALID.getCode(), ApiStatusCode.ACCOUNT_OLD_PWD_INVALID.getDescription());
            }
        }

        // 执行更改密码
        String encryptNewPassword = AESUtil.encryptPassword(dto.getNewPassword());
        orgUserService.updatePasswordByPhoneNumber(encryptNewPassword, phoneNumber);
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 重置专家密码
     *
     * @param dto 入参
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.EXPERT, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_RESETPWD, operDesc = "")
    @PostMapping("/resetPassword")
    public ApiResultDTO resetPassword(@RequestBody @Valid OrgUserRestPasswordParamsDTO dto) {
        boolean checkCaptchaState = captchaService.check(CaptchaType.FORGET_PASSWORD, dto.getPhoneNumber(), dto.getCode());
        if (!checkCaptchaState) {
            // 如果验证码校验失败
            return ApiResultGenerator.create(ApiStatusCode.CAPTCHA_INVALID.getCode(), ApiStatusCode.CAPTCHA_INVALID.getDescription());
        }
        // 执行密码重置
        orgUserService.resetPassword(dto.getPhoneNumber(), dto.getNewPassword());
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 绑定手机号码
     *
     * @param dto 入参
     * @return 执行反馈
     */
    @PostMapping("/bindPhoneNumber")
    @RequiresPermissions("expert:info:change:phone")
    public ApiResultDTO bindPhoneNumber(@RequestBody @Valid OrgUserBindPhoneNumberDto dto) {
        boolean checkCaptchaState = captchaService.check(CaptchaType.BIND, dto.getPhoneNumber(), dto.getCode());
        if (!checkCaptchaState) {
            // 如果验证码校验失败
            return ApiResultGenerator.create(ApiStatusCode.CAPTCHA_INVALID.getCode(), ApiStatusCode.CAPTCHA_INVALID.getDescription());
        }
        // 执行重绑手机号
        try {
            orgUserService.bindPhoneNumber(OrgAccountHelper.getUserId(), dto.getPhoneNumber());
            return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
        } catch (PhoneNumberExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_EXISTED.getCode(), ApiStatusCode.ACCOUNT_EXISTED.getDescription());
        }
    }

    /**
     * 修改个人信息
     *
     * @param dto 参数
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.EXPERT, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_UPDATE, operDesc = "专家修改个人信息")
    @PostMapping("/updateInfo")
    public ApiResultDTO updateInfo(@RequestBody OrgUserParamsDto dto) {
        try {
            orgUserService.updateInfo(dto);
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResultGenerator.create(ApiStatusCode.ERROR.getCode(), ApiStatusCode.ERROR.getDescription());
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 切换组织机构
     *
     * @return 反馈
     */
    @PostMapping("/switchOrg")
    public ApiResultDTO switchOrg(@RequestBody OrgParamsDto dto) {
        // 设置切换后的机构id
        OrgAccountHelper.setOrgId(dto.getId());
        // 清楚权限相关缓存
        orgUsernamePasswordRealm.clearCachedAuthorizationInfo(OrgAccountHelper.getUsername());
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 获取org列表与当前org
     *
     * @return 反馈
     */
    @PostMapping("/readOrgs")
    public ApiResultDTO readOrgs() {
        // 返回当前登录机构与可切换登录机构
        List<OrgUserRelPo> pos = orgService.readOrgsByAccId();
        List<OrgUserRelResultDto> dtos = orgUserRelMapper.pos2dtos(pos);
        Map<String, Object> result = new HashMap<>(1);
        result.put("orgUserRels", dtos);
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), result);
    }

}
